// --------------------------------------------------------------------------------------------------------------------
// <copyright file="BarclaysDataParser.cs" company="Concept Architecture">
//   (c) 2010 Muhammad Umer Farooq
// </copyright>
// <summary>
//   Defines the <seealso cref="BarclaysDataParser" /> type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Hisaab.Business.Parser
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics.Contracts;
    using System.Linq;
    using Hisaab.Business.Entities;
    using Hisaab.Data.Interfaces;
    using LINQtoCSV;
    using Microsoft.Practices.ServiceLocation;

    /// <summary>
    /// Defines the <seealso cref="BarclaysDataParser"/> type.
    /// </summary>
    public class BarclaysDataParser : IBankDataParser
    {
        /// <summary>
        /// Member variable _accountRepository
        /// </summary>
        private readonly IAccountRepository _accountRepository;

        /// <summary>
        /// Initializes a new instance of the <see cref="BarclaysDataParser"/> class.
        /// </summary>
        public BarclaysDataParser()
            : this(ServiceLocator.Current.GetInstance<IAccountRepository>())
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="BarclaysDataParser"/> class.
        /// </summary>
        /// <param name="accountRepository">The account manager.</param>
        public BarclaysDataParser(IAccountRepository accountRepository)
        {
            Contract.Requires<ArgumentNullException>(accountRepository != null);

            _accountRepository = accountRepository;
        }

        /// <summary>
        /// Imports the CSV.
        /// </summary>
        /// <param name="fileName">The fileName.</param>
        /// <returns>Transactions imported from csv</returns>
        public IEnumerable<Transaction> ImportCsv(string fileName)
        {
            var context = new CsvContext();
            var natwestData = context.Read<BarclaysDataItem>(
                fileName,
                new CsvFileDescription { SeparatorChar = ',', FirstLineHasColumnNames = true });

            var result = natwestData
                .Select(dataItem => new Transaction
                {
                    Date = dataItem.Date,
                    Amount = Math.Abs(dataItem.Amount),
                    TransactionType = dataItem.Amount < 0 ? TransactionTypes.Expanse : TransactionTypes.Income,
                    Title = dataItem.Memo,
                    Account = GetAccountIdFromAccountNumber(dataItem.Account)
                })
                .ToList();

            return result.ToList();
        }

        /// <summary>
        /// Gets the account id from account number.
        /// </summary>
        /// <param name="accountNumber">The account number.</param>
        /// <returns>Account Id from name</returns>
        private int GetAccountIdFromAccountNumber(string accountNumber)
        {
            string accNumber = accountNumber.Split(' ')[1].Trim();
            var account = _accountRepository
                            .Query(new Data.Entities.Account { AccountNumber = accNumber })
                            .FirstOrDefault();

            return account != null ? account.Id : 0;
        }

        /// <summary>
        /// Defines the <seealso cref="BarclaysDataParser.BarclaysDataItem"/> type.
        /// Number,Date,Account,Amount,Subcategory,Memo
        /// </summary>
        public class BarclaysDataItem
        {
            /// <summary>
            /// Gets or sets the number.
            /// </summary>
            /// <value>The number.</value>
            [CsvColumn(Name = "Number", FieldIndex = 0)]
            public string Number { get; set; }

            /// <summary>
            /// Gets or sets the date.
            /// </summary>
            /// <value>
            /// The date in format dd/MM/YYYY e.g. 31/01/2012
            /// </value>
            [CsvColumn(Name = "Date", FieldIndex = 1)]
            public DateTime Date { get; set; }

            /// <summary>
            /// Gets or sets the sort code and account number.
            /// </summary>
            /// <value>
            /// Account sortcode and number e.g. 12-34-56 12345678
            /// </value>
            [CsvColumn(Name = "Account", FieldIndex = 2)]
            public string Account { get; set; }

            /// <summary>
            /// Gets or sets the value.
            /// </summary>
            /// <value>
            /// The value.
            /// </value>
            [CsvColumn(Name = "Amount", FieldIndex = 3)]
            public decimal Amount { get; set; }

            /// <summary>
            /// Gets or sets the Subcategory.
            /// </summary>
            /// <value>
            /// The Subcategory.
            /// </value>
            [CsvColumn(Name = "Subcategory", FieldIndex = 4)]
            public string Subcategory { get; set; }

            /// <summary>
            /// Gets or sets the memo.
            /// </summary>
            /// <value>
            /// The memo of the transaction.
            /// </value>
            [CsvColumn(Name = "Memo", FieldIndex = 5)]
            public string Memo { get; set; }
        }
    }
}